#ifndef MODBUSRTUMASTER_H
#define MODBUSRTUMASTER_H

#include <QWidget>
#include <QSerialPortInfo>
//#include <serialport.h>
//#include "ModbusMaster/serialport.h"
#include "Modbus/ModbusRTU/serialport.h"
#include <QDateTime>
#include <QSettings>
#include <QStandardItemModel>
#include <QFile>
#include <QDir>
#include <QMessageBox>
#include <QFileDialog>
#include <QTimer>
#include <QTableView>
#include <QMutex>



namespace MODBUS_WND_TXRX_RESULT_COLUMNS
{
    enum {
        TIMESTAMP           ,
        STATUS              ,
        MODE                ,
        RAWDATA             ,
        CRC                 ,
        SLAVE_ADDR          ,
        FUNCTION            ,
        INFO                ,
        COUNT
    };
}
namespace MODBUS_WND_TX_QUEUE_COLUMNS
{
    enum {
        ENABLE           ,
        HEX              ,
        ASCII           ,
        COMMENT          ,
        COUNT
    };
}

class ModbusRtuMaster : public QWidget
{
    Q_OBJECT

public:

    struct ComPortSetting{

        QString cmbComPort;
        QString cmbBaudrate;
        QString cmbDataBits;
        QString cmbParity;
        QString cmbStopBits;
    };

    ComPortSetting mComPortSetting;
    explicit ModbusRtuMaster(QString port,QString baud,QString dataBits,QString parity,QString stopBits,QWidget *parent = 0);
    ~ModbusRtuMaster();
    static ModbusRtuMaster *getobj(QString port,QString baud,QString dataBits,QString parity,QString stopBits);
    static bool check_ModbusRTU_CRC16(QByteArray buf, quint16 &result);
    static quint16 ModbusRTU_CRC16 (const char *buf, quint16 wLength);
    static quint8 LSBUS_sum(QByteArray buf);
    static QByteArray toHexString(QByteArray buf);
    void createConnection();
    void resetRxCount() { m_rxCount = 0; emit sgRxCountChanged(); }
    void resetTxCount() { m_txCount = 0; emit sgTxCountChanged(); }
    void resetErrorCount() { m_errorCount = 0; emit sgErrorCountChanged(); }
    void addRxCount() { m_rxCount++; emit sgRxCountChanged(); }
    void addTxCount() { m_txCount++; emit sgTxCountChanged(); }
    void addErrorCount() { m_errorCount++; emit sgErrorCountChanged(); }
    int onParseData(QStringList &parsedData, QByteArray data);
    int onParseData(QStringList &parsedData, QByteArray data,QByteArray info);
    void readSettings();
    void closeEvent(QCloseEvent * event);
    void addDataToTxRxResultModel(QStringList info);
    void addDataToTxPktQueueModel(QStringList parsedData);
    QByteArray makeRTUFrame(QByteArray slaveAddr, QByteArray functionCode, QByteArray startAddr,
                                       QByteArray numOfRegister, QByteArray byteCount, const QByteArray writeData);
    QByteArray makeLSBUSFrame(QByteArray slaveAddr, QByteArray functionCode, QByteArray startAddr,
                                       QByteArray numOfRegister, QByteArray byteCount, const QByteArray writeData);

public slots:
    void onPortConnected();
    void onPortDisconnected();
    void onPortResponseTimeout();
    void onTryConnectedPort();
    void onBtnCloseClicked();
    void onRecvedData(QByteArray data);
    void onSendedData(QByteArray data);
    void onRecvedErrorData(QByteArray data);
    quint32 onCmbBaudrateTextChanged(QString str);
    quint32 onCmbDataBitsTextChanged(QString str);
    quint32 onCmbParityTextChanged(QString str);
    quint32 onCmbStopBitsTextChanged(QString str);

    void onChkAutoSendToggled(bool checked);
    void onChkIgnoreAckToggled(bool checked);
    void onLineModbusEditingFinished();

    void onBtnManualSendClicked();
    void onBtnScreenClearClicked();
    void removeModelTxRxResult();
    void onBtnRefreshClicked();

    void onRxCountChanged();
    void onTxCountChanged();
    void onErrorCountChanged();
    void onT15IntervalChanged();
    void onT35IntervalChanged();

    void readDataFromModbusSlave   (QString mSlaveAddr,QString mFunctionCode,QString mStartAddr,QString mNumOfRegister,QString mCommMode,QString mbyteCount);//读规范号参数
    void btnTxQueueFileOpenClicked()  ;
    void btnTxqueueFileSaveClicked()  ;
    void onModelTxPktQueueDataChanged(QModelIndex topLeft, QModelIndex bottomRight);
    void onTimerAutoSendTimeout();
    void onModelTxResultRowInserted(const QModelIndex &parent, int first, int last);
    void sendModelTxPktQueue(int index );
    void onReadyEntered();
    void onReceiveWriteList(QStringList);

signals:
    void sgRxCountChanged();
    void sgTxCountChanged();
    void sgErrorCountChanged();
    void sgConnected(QString str);
    void sgDisconnected(QString str);
    void sendWriteList(QStringList);
    void toggleAutoSend(bool);

    void sendStandardData_fromModbus(QString);
    void sendWarnData_fromModbus(int);

public:
    void writeCmd(QString slaveAddr, QString functionCode,QString startAddr,QString numOfRegister,QString commMode,QString byteCount,QString inputDataString,bool intputFlag);
    void toggleAutoSendFun(bool check);
private:
    static ModbusRtuMaster        *m_modbusWndInstance;
    SerialPort*             m_port;
    QStandardItemModel*     m_modelTxPktQueue;
    QStandardItemModel*     m_modelTxRxResult;
    quint64                 m_rxCount;
    quint64                 m_txCount;
    quint64                 m_errorCount;
    quint64                 m_txRxResultMaxRow;
    QThread*                m_threadForSerial;
    QTimer*                 m_timerAutoSend;
    QTableView              *m_viewTxQueueData;
    QTableView              *m_viewTxRxResult;
    QMutex                  m_mutexFotSerial;
    QMutex                  m_mutex;
};

#endif // MODBUSRTUMASTER_H
